// InstrumentLogAspect.java
package cn.iocoder.yudao.module.instrument.aop;

import cn.iocoder.yudao.module.instrument.log.InstrumentLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class InstrumentLogAspect {

    // 配置织入点
    @Pointcut("@annotation(cn.iocoder.yudao.module.instrument.log.InstrumentLog)")
    public void logPointCut() {
    }

    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
        handleLog(joinPoint, null, jsonResult);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        handleLog(joinPoint, e, null);
    }

    protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {
        try {
            // 获得注解
            InstrumentLog controllerLog = getAnnotationLog(joinPoint);
            if (controllerLog == null) {
                return;
            }

            // 获取当前被拦截方法详情信息
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] args = joinPoint.getArgs();

            StringBuilder sb = new StringBuilder();
            sb.append("操作模块: ").append(controllerLog.value()).append(", ");
            sb.append("方法: ").append(className).append(".").append(methodName).append("(), ");
            
            // 参数处理
            if (args.length > 0) {
                sb.append("参数: ");
                for (Object arg : args) {
                    sb.append(arg).append(" ");
                }
            }
            
            // 返回值处理
            if (jsonResult != null) {
                sb.append(", 返回值: ").append(jsonResult.toString());
            }
            
            // 异常处理
            if (e != null) {
                sb.append(", 异常信息: ").append(e.getMessage());
                log.error(sb.toString(), e);
            } else {
                log.info(sb.toString());
            }
        } catch (Exception exp) {
            // 记录本地异常日志
            log.error("==前置通知异常==");
            log.error("异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private InstrumentLog getAnnotationLog(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        if (method != null) {
            return method.getAnnotation(InstrumentLog.class);
        }
        return null;
    }
}
